#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "lwip/inet.h"

#include "wifi-sta.h"
#include "wifi-ap.h"
#include "nvs.h"
// forward from web_server.c
void start_web_services(void);

static const char *TAG_STA = "WiFi Sta";
static const char *TAG_AP = "WiFi SoftAP";

#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

/**
 * @brief WiFi主函数 - 初始化并配置ESP32的WiFi STA+AP双模式功能
 * 
 * 该函数完成以下主要任务：
 * 1. 初始化网络接口、事件循环和 NVS 存储（NVS = Non-Volatile Storage（非易失性存储））
 * 2. 从NVS读取已保存的WiFi凭据
 * 3. 配置WiFi工作在STA+AP双模式
 * 4. 初始化WiFi AP接口和STA接口
 * 5. 应用保存的WiFi凭据（如果有）
 * 6. 启动WiFi并等待STA连接
 * 7. 配置AP的DNS和NAPT功能以实现网络共享
 * 8. 启动Web服务（HTTP和WebSocket）
 */
void wifi_main(void){
    // 初始化网络接口子系统
    ESP_ERROR_CHECK(esp_netif_init());
    // 创建默认事件循环
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    // 初始化NVS（非易失性存储）用于保存WiFi配置
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // 如果NVS分区已满或版本不匹配，则擦除并重试
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    /* 从NVS（命名空间："wifi"）读取已保存的WiFi凭据 */
    char stored_ssid[33] = {0};
    char stored_password[65] = {0};
    size_t ssid_len = sizeof(stored_ssid);
    size_t pwd_len = sizeof(stored_password);
    nvs_handle_t nvs_handle;
    esp_err_t nerr = nvs_open("wifi", NVS_READONLY, &nvs_handle);
    if (nerr == ESP_OK) {
        nerr = nvs_get_str(nvs_handle, "ssid", stored_ssid, &ssid_len);
        if (nerr == ESP_OK) {
            nerr = nvs_get_str(nvs_handle, "password", stored_password, &pwd_len);
            if (nerr != ESP_OK) {
                /* 密码可能为空或未设置 */
                stored_password[0] = '\0';
            }
            ESP_LOGI(TAG_STA, "Loaded SSID from NVS: %s", stored_ssid);
        }
        nvs_close(nvs_handle);
    }

    /* 为WiFi station设置事件组 - 用于同步WiFi连接状态 */
    wifi_sta_setup_event_group();

    /* 注册事件处理器 - 用于处理WiFi相关事件 */
    wifi_sta_register_event_handlers();
    wifi_ap_register_event_handlers();

    /* 初始化WiFi - 使用默认配置 */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // 设置WiFi模式为AP+STA双模式
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));

    /* 初始化AP接口 - 创建并配置WiFi接入点 */
    ESP_LOGI(TAG_AP, "ESP_WIFI_MODE_AP");
    esp_netif_t *esp_netif_ap = wifi_init_softap();

    /* 初始化STA接口 - 创建并配置WiFi客户端 */
    ESP_LOGI(TAG_STA, "ESP_WIFI_MODE_STA");
    esp_netif_t *esp_netif_sta = wifi_init_sta();

    /* 如果NVS中包含WiFi凭据，则在启动前应用到STA接口 */
    if (strlen(stored_ssid) > 0) {
        wifi_config_t cfg2 = {0};
        strncpy((char *)cfg2.sta.ssid, stored_ssid, sizeof(cfg2.sta.ssid)-1);
        strncpy((char *)cfg2.sta.password, stored_password, sizeof(cfg2.sta.password)-1);
        ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &cfg2));
        ESP_LOGI(TAG_STA, "Applied saved STA config from NVS: %s", stored_ssid);
    }

    /* 启动WiFi */
    ESP_ERROR_CHECK(esp_wifi_start());

    /* 等待WiFi station连接到指定的接入点 */
    EventBits_t bits = wifi_sta_wait_for_connection();

    /* 检查连接状态 */
    wifi_sta_check_connection_status(bits);

    /* 如果已连接，为softAP设置DNS地址 */
    if (bits & WIFI_CONNECTED_BIT) {
        softap_set_dns_addr(esp_netif_ap, esp_netif_sta);
    }

    /* 将STA接口设置为默认网络接口 - 用于默认网络通信 */
    wifi_sta_set_as_default_interface(esp_netif_sta);

    /*
     * 启用AP网络接口上的NAPT功能
     * NAPT(Network Address and Port Translation)即网络地址和端口转换
     * 这一功能使连接到ESP32 AP的设备能够通过ESP32的STA接口访问外部网络
     * 实现了类似路由器的网络共享功能
     */
    wifi_ap_enable_napt(esp_netif_ap);

    /* 启动Web服务（HTTP服务器和WebSocket服务器）- 用于提供Web配置界面 */
    start_web_services();
}